#include "PMDLoader.h"

const Color4 operator *(const Color4& pColor1, const Color4& pColor2)
{
	Color4 tmp = pColor1;
	tmp *= pColor2;
	return tmp;
}

const Color3 operator *(const Color3& pColor1, const Color3& pColor2)
{
	Color3 tmp = pColor1;
	tmp *= pColor2;
	return tmp;
}


bool PMDLoader::Load(const char* pFileName, PMDMesh* pMesh)
{
	std::ifstream lFile(pFileName, std::ios::in | std::ios::binary);

	if (!lFile) return false;

	//header
	lFile.read(reinterpret_cast<char*>(&pMesh->mHeader), sizeof(HeaderInfo));
	//vertex count
	lFile.read(reinterpret_cast<char*>(&pMesh->mVertexCount), sizeof(unsigned long));
	//vertex
	pMesh->mVertexs = new VertexInfo[pMesh->mVertexCount];
	lFile.read(reinterpret_cast<char*>(pMesh->mVertexs), (sizeof(VertexInfo) * pMesh->mVertexCount));
	//suface count
	lFile.read(reinterpret_cast<char*>(&pMesh->mSurfaceVertexCount), (sizeof(unsigned long)));
	//surface
	pMesh->mSurfaces = new unsigned short[pMesh->mSurfaceVertexCount];
	lFile.read(reinterpret_cast<char*>(pMesh->mSurfaces), (sizeof(unsigned short) * pMesh->mSurfaceVertexCount));
	//material count
	lFile.read(reinterpret_cast<char*>(&pMesh->mMaterialCount), (sizeof(unsigned long)));
	//material
	pMesh->mMaterials = new PMDMaterial[pMesh->mMaterialCount];
	lFile.read(reinterpret_cast<char*>(pMesh->mMaterials), (sizeof(PMDMaterial) * pMesh->mMaterialCount));
	//bone count
	lFile.read(reinterpret_cast<char*>(&pMesh->mBoneCount), (sizeof(unsigned short)));
	//bone
	pMesh->mBones = new BoneInfo[pMesh->mBoneCount];
	lFile.read(reinterpret_cast<char*>(pMesh->mBones), (sizeof(BoneInfo) * pMesh->mBoneCount));
	//ik count
	lFile.read(reinterpret_cast<char*>(&pMesh->mIkCount), (sizeof(unsigned short)));
	//ik 
	pMesh->mIks = new IKInfo[pMesh->mIkCount];
	for (int lIndex = 0; lIndex < pMesh->mIkCount; ++lIndex)
	{
		lFile.read(reinterpret_cast<char*>(&pMesh->mIks[lIndex]), ((sizeof(IKInfo) - sizeof(unsigned short*))));
		if (pMesh->mIks[lIndex].mIkLinkCount)
		{
			pMesh->mIks[lIndex].mIkLinkBoneIndexList = new unsigned short[(int)pMesh->mIks[lIndex].mIkLinkCount];
			lFile.read(reinterpret_cast<char*>(pMesh->mIks[lIndex].mIkLinkBoneIndexList),
				(sizeof(unsigned short) * (int)pMesh->mIks[lIndex].mIkLinkCount));
		}
	}

	//skin count
	lFile.read(reinterpret_cast<char*>(&pMesh->mSkinCount), (sizeof(unsigned short)));
	//skin
	pMesh->mSkins = new SkinInfo[pMesh->mSkinCount];
	for (int lIndex = 0; lIndex < pMesh->mSkinCount; ++lIndex)
	{
		lFile.read(reinterpret_cast<char*>(&pMesh->mSkins[lIndex]), (sizeof(SkinInfo) - sizeof(SkinVertexInfo*)));
		if (pMesh->mSkins[lIndex].mSkinVertexCount)
		{
			pMesh->mSkins[lIndex].mSkinVertexList = new SkinVertexInfo[pMesh->mSkins[lIndex].mSkinVertexCount];
			lFile.read(reinterpret_cast<char*>(pMesh->mSkins[lIndex].mSkinVertexList),
				sizeof(SkinVertexInfo) * pMesh->mSkins[lIndex].mSkinVertexCount);
		}
	}

	//skin display frame count
	lFile.read(reinterpret_cast<char*>(&pMesh->mSkinDisplayFrameCount), sizeof(unsigned char));
	//skin display index
	pMesh->mSkinIndex = new unsigned short[(int)pMesh->mSkinDisplayFrameCount];
	lFile.read(reinterpret_cast<char*>(pMesh->mSkinIndex), sizeof(unsigned short) * (int)pMesh->mSkinDisplayFrameCount);

	//bone display frame name count
	lFile.read(reinterpret_cast<char*>(&pMesh->mBoneDisplayFrameNameCount), sizeof(unsigned char));
	//display frame name
	pMesh->mDisplayFrameName = new FrameName[pMesh->mBoneDisplayFrameNameCount];
	lFile.read(reinterpret_cast<char*>(pMesh->mDisplayFrameName), sizeof(FrameName) * (int)pMesh->mBoneDisplayFrameNameCount);

	lFile.read(reinterpret_cast<char*>(&pMesh->mBoneDisplayFrameCount), sizeof(unsigned long));

	pMesh->mBoneDisplayFrame = new BoneDisplayFrameInfo[pMesh->mBoneDisplayFrameCount];
	lFile.read(reinterpret_cast<char*>(pMesh->mBoneDisplayFrame), sizeof(BoneDisplayFrameInfo) * pMesh->mBoneDisplayFrameCount);

	//english
	lFile.read(reinterpret_cast<char*>(&pMesh->mEnglishCompatibility.mEnglishNameCompatibility), sizeof(bool));
	if (pMesh->mEnglishCompatibility.mEnglishNameCompatibility)
	{
		lFile.read(reinterpret_cast<char*>(pMesh->mEnglishCompatibility.mModelNameEn), sizeof(Name));

		lFile.read(reinterpret_cast<char*>(&pMesh->mEnglishCompatibility.mCommentEn), sizeof(Comment));

		if (pMesh->mBoneCount > 0)
		{
			pMesh->mEnglishCompatibility.mBoneNameEn = new Name[pMesh->mBoneCount];
			lFile.read(reinterpret_cast<char*>(pMesh->mEnglishCompatibility.mBoneNameEn), sizeof(Name) * pMesh->mBoneCount);
		}

		if (pMesh->mSkinCount > 1)
		{
			pMesh->mEnglishCompatibility.mSkinNameEn = new Name[pMesh->mSkinCount - 1];
			lFile.read(reinterpret_cast<char*>(pMesh->mEnglishCompatibility.mSkinNameEn), sizeof(Name) * (pMesh->mSkinCount - 1));
		}

		lFile.read(reinterpret_cast<char*>(pMesh->mEnglishCompatibility.mDisplayFrameNameEn), sizeof(FrameName));
	}

	//toon texture
	lFile.read(reinterpret_cast<char*>(pMesh->mToonTextureName), sizeof(char) * 1000);

	//rigid body count
	lFile.read(reinterpret_cast<char*>(&pMesh->mRigidBodyCount), sizeof(unsigned long));
	//rigid body
	pMesh->mRigidBody = new RigidBodyInfo[pMesh->mRigidBodyCount];
	lFile.read(reinterpret_cast<char*>(pMesh->mRigidBody), sizeof(RigidBodyInfo) * pMesh->mRigidBodyCount);
	//joint count
	lFile.read(reinterpret_cast<char*>(&pMesh->mJointCount), sizeof(unsigned long));
	//joint
	pMesh->mJoints = new JointInfo[pMesh->mJointCount];
	lFile.read(reinterpret_cast<char*>(pMesh->mJoints), sizeof(JointInfo) * pMesh->mJointCount);

	//texture
	pMesh->mMaterialTextures.resize(pMesh->mMaterialCount);
	for (unsigned int i = 0; i < pMesh->mMaterialCount; ++i)
	{
		TextureContainer* lTexContainer = &pMesh->mMaterialTextures[i];
		pMesh->mMaterials[i].LoadMaterialTexture(pFileName, lTexContainer);
	}
	//create array
	pMesh->CreateVertexArray();

	//if (!CreateData(pMesh))
	//	return false;

	return true;
}

void PMDLoader::Release(PMDMesh* pMesh)
{
	if (!pMesh) return;

	if (pMesh->mVertexs) delete[] pMesh->mVertexs;
	if (pMesh->mSurfaces) delete[] pMesh->mSurfaces;
	if (pMesh->mMaterials) delete[] pMesh->mMaterials;
	if (pMesh->mBones) delete pMesh->mBones;
	for (int lIndex = 0; lIndex < pMesh->mIkCount; ++lIndex)
		if (pMesh->mIks[lIndex].mIkLinkBoneIndexList)
			delete[] pMesh->mIks[lIndex].mIkLinkBoneIndexList;

	for (int lIndex = 0; lIndex < pMesh->mSkinCount; ++lIndex)
		if (pMesh->mSkins[lIndex].mSkinVertexList)
			delete[] pMesh->mSkins[lIndex].mSkinVertexList;

	if (pMesh->mIks) delete[] pMesh->mIks;
	if (pMesh->mSkins) delete[] pMesh->mSkins;
	if (pMesh->mSkinIndex) delete[] pMesh->mSkinIndex;
	if (pMesh->mDisplayFrameName) delete[] pMesh->mDisplayFrameName;
	if (pMesh->mBoneDisplayFrame) delete[] pMesh->mBoneDisplayFrame;
	if (pMesh->mEnglishCompatibility.mBoneNameEn) delete[] pMesh->mEnglishCompatibility.mBoneNameEn;
	if (pMesh->mEnglishCompatibility.mSkinNameEn) delete[] pMesh->mEnglishCompatibility.mSkinNameEn;
	if (pMesh->mRigidBody) delete[] pMesh->mRigidBody;
	if (pMesh->mJoints) delete[] pMesh->mJoints;

	delete pMesh;
}